﻿namespace TestTool.GUI.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Threading;
    using TestTool.GUI.Data;
    using TestTool.GUI.Enums;
    using TestTool.GUI.Utils;
    using TestTool.GUI.Views;
    using TestTool.HttpTransport;
    using TestTool.HttpTransport.Interfaces;
    using TestTool.Tests.Common.TestEngine;
    using TestTool.Tests.Common.Transport;

    internal class RequestsController : Controller<IRequestsView>
    {
        private string _address;
        private List<RequestFolder> _folders;
        private Dictionary<string, RequestFolder> _foldersList;
        private string _request;
        private bool _requestPending;
        private string _requestsRootPath;
        private List<RequestFile> _rootFiles;
        private TestSemaphore _semaphore;
        private Dictionary<DutService, string> _serviceAddresses;
        private bool _shutdown;

        public RequestsController(IRequestsView view) : base(view)
        {
            this._folders = new List<RequestFolder>();
            this._rootFiles = new List<RequestFile>();
            this._foldersList = new Dictionary<string, RequestFolder>();
            this._semaphore = new TestSemaphore();
            this._serviceAddresses = new Dictionary<DutService, string>();
        }

        private RequestFile AddFileToHierarchy(string path)
        {
            if (!path.StartsWith(this.RequestsRootPath))
            {
                RequestFile file = new RequestFile(new FileInfo(path));
                base.View.AddFile(file, null);
                return file;
            }
            List<string> list = new List<string>();
            string directoryName = Path.GetDirectoryName(path);
            RequestFolder parentFolder = null;
            while (!this._foldersList.ContainsKey(directoryName) && (directoryName != this._requestsRootPath))
            {
                int length = directoryName.LastIndexOf(Path.DirectorySeparatorChar);
                list.Insert(0, directoryName.Substring(length + 1));
                directoryName = directoryName.Substring(0, length);
                if (!directoryName.Contains<char>(Path.DirectorySeparatorChar))
                {
                    directoryName = this.RequestsRootPath;
                    list.Clear();
                    break;
                }
            }
            if (this._foldersList.ContainsKey(directoryName))
            {
                parentFolder = this._foldersList[directoryName];
            }
            RequestFolder folder = null;
            RequestFolder folder3 = parentFolder;
            foreach (string str2 in list)
            {
                string str3 = Path.Combine(directoryName, str2);
                RequestFolder folder4 = new RequestFolder(Directory.CreateDirectory(str3));
                if (folder == null)
                {
                    folder = folder4;
                }
                if (this._foldersList.ContainsKey(directoryName))
                {
                    this._foldersList[directoryName].Folders.Add(folder4);
                }
                else
                {
                    this._folders.Add(folder4);
                }
                this._foldersList.Add(folder4.Path, folder4);
                directoryName = str3;
                folder3 = folder4;
            }
            RequestFile item = new RequestFile(new FileInfo(path));
            if (folder3 != null)
            {
                folder3.Requests.Add(item);
            }
            else
            {
                this._rootFiles.Add(item);
            }
            if (folder == null)
            {
                base.View.AddFile(item, parentFolder);
                return item;
            }
            base.View.AddFolder(folder, parentFolder);
            return item;
        }

        private void AddFolderToDictionary(RequestFolder folder)
        {
            this._foldersList.Add(folder.Path, folder);
            foreach (RequestFolder folder2 in folder.Folders)
            {
                this.AddFolderToDictionary(folder2);
            }
        }

        public string ApplySecurity(string request)
        {
            DeviceEnvironment deviceEnvironment = ContextController.GetDeviceEnvironment();
            DebugInfo debugInfo = ContextController.GetDebugInfo();
            string str = request;
            if (debugInfo.Security == Security.WS)
            {
                if (!string.IsNullOrEmpty(deviceEnvironment.Credentials.UserName))
                {
                    str = new SoapHelper().ApplySecurity(request, deviceEnvironment.Credentials.UserName, deviceEnvironment.Credentials.Password, deviceEnvironment.Credentials.UseUTCTimeStamp, true);
                }
                return str;
            }
            SoapHelper helper2 = new SoapHelper();
            return helper2.RemoveSecurity(request);
        }

        public void DeleteRequest(RequestFile file)
        {
            if (!File.Exists(file.Path))
            {
                throw new FileNotFoundException("File not found", file.Path);
            }
            File.Delete(file.Path);
        }

        public override void Initialize()
        {
            string requestsRootPath = this.RequestsRootPath;
            if (Directory.Exists(requestsRootPath))
            {
                RequestFolder folder = new RequestFolder(new DirectoryInfo(requestsRootPath));
                folder.Load();
                this._folders.AddRange(folder.Folders);
                foreach (RequestFolder folder2 in folder.Folders)
                {
                    this.AddFolderToDictionary(folder2);
                }
                this._rootFiles.AddRange(folder.Requests);
                base.View.DisplayFolders(folder);
            }
        }

        public override void LoadSavedContext(SavedContext context)
        {
            if (context.RequestsInfo != null)
            {
                base.View.Service = context.RequestsInfo.Service;
                base.View.ServiceAddress = context.RequestsInfo.ServiceAddress;
                this._serviceAddresses[context.RequestsInfo.Service] = context.RequestsInfo.ServiceAddress;
            }
        }

        public RequestFile SaveRequest(string path, string content)
        {
            Func<RequestFile, bool> func = null;
            Func<RequestFile, bool> func2 = null;
            if (File.Exists(path))
            {
                File.Delete(path);
                string directoryName = Path.GetDirectoryName(path);
                if (this._foldersList.ContainsKey(directoryName))
                {
                    RequestFolder parentFolder = this._foldersList[directoryName];
                    if (func == null)
                    {
                        func = r => r.FileName == Path.GetFileName(path);
                    }
                    RequestFile item = Enumerable.Where<RequestFile>(parentFolder.Requests, func).FirstOrDefault<RequestFile>();
                    if (item != null)
                    {
                        parentFolder.Requests.Remove(item);
                        base.View.DeleteFile(item, parentFolder);
                    }
                }
                else
                {
                    if (func2 == null)
                    {
                        func2 = r => r.FileName == Path.GetFileName(path);
                    }
                    RequestFile file = Enumerable.Where<RequestFile>(this._rootFiles, func2).FirstOrDefault<RequestFile>();
                    base.View.DeleteFile(file, null);
                }
            }
            TextWriter writer = new StreamWriter(File.Create(path));
            writer.Write(content);
            writer.Close();
            return this.AddFileToHierarchy(path);
        }

        public void SelectService(DutService service)
        {
            if (this._serviceAddresses.ContainsKey(service))
            {
                base.View.ServiceAddress = this._serviceAddresses[service];
            }
            else if (service == DutService.DeviceManagement)
            {
                base.View.ServiceAddress = "/onvif/device_service";
            }
            else
            {
                base.View.ServiceAddress = string.Empty;
            }
        }

        public void SendRequest()
        {
            base.ReportOperationStarted();
            this._serviceAddresses[base.View.Service] = base.View.ServiceAddress;
            this._request = base.View.Request;
            this._address = base.View.ServiceAddress;
            new Thread(new ThreadStart(this.SendRequestInternal)) { CurrentUICulture = CultureInfo.InvariantCulture }.Start();
        }

        private void SendRequestInternal()
        {
            try
            {
                DeviceEnvironment deviceEnvironment = ContextController.GetDeviceEnvironment();
                CredentialsProvider credentialsProvider = new CredentialsProvider {
                    Security = ContextController.GetDebugInfo().Security,
                    Username = deviceEnvironment.Credentials.UserName,
                    Password = deviceEnvironment.Credentials.Password
                };
                HttpClient client = new HttpClient(this._address, deviceEnvironment.Timeouts.Message, this._semaphore, credentialsProvider);
                this._requestPending = true;
                string response = client.SendSoapMessage(this._request);
                if (!this._shutdown)
                {
                    base.View.DisplayResponse(response);
                }
            }
            catch (Exception exception)
            {
                if (!this._shutdown)
                {
                    base.View.DisplayResponse(exception.Message);
                }
            }
            finally
            {
                this._requestPending = false;
                if (!this._shutdown)
                {
                    base.ReportOperationCompleted();
                }
            }
        }

        public override void Stop()
        {
            this._shutdown = true;
            if (this._requestPending)
            {
                this._semaphore.Stop();
            }
        }

        public override void UpdateContext()
        {
            RequestsInfo info = new RequestsInfo {
                Service = base.View.Service,
                ServiceAddress = base.View.ServiceAddress
            };
            ContextController.UpdateRequestsInfo(info);
        }

        public void UpdateRequestSecurity()
        {
            string request = base.View.Request;
            base.View.Request = this.ApplySecurity(request);
        }

        public override void UpdateView()
        {
            base.View.Request = this.ApplySecurity(base.View.Request);
        }

        public override bool RequestPending
        {
            get
            {
                return this._requestPending;
            }
        }

        public string RequestsRootPath
        {
            get
            {
                if (this._requestsRootPath == null)
                {
                    string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                    this._requestsRootPath = Path.Combine(folderPath, @"ONVIF\ONVIF Device Test Tool\Requests");
                }
                return this._requestsRootPath;
            }
        }
    }
}

